/*
 * display.h
 *
 * Header file for display framework.
 *
 * Based on Nigel Batten's TellyMate notes and code available at
 *  http://www.batsocks.co.uk/readme/art_SerialVideo_1.htm
 *
 * Copyright (c) 2010, Alan Green.
 * Contactable at <firstname>.<lastname>@gmail.com
 *
 * Copyright (c) 2009, Nigel Batten.
 * Contactable at <firstname>.<lastname>@mail.com
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 	1.	Redistributions of source code must retain the above copyright
 * 		notice, this list of conditions and the following disclaimer.
 * 	2.	Redistributions in binary form must reproduce the above copyright
 * 		notice, this list of conditions and the following disclaimer in the
 * 		documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * ===============================================
 */

#ifndef DISPLAY_H_
#define DISPLAY_H_

#include <stdint.h>
#include <avr/io.h>

//
// Pin uses - all port B
//

// Sync on PB1 = OC1A, D9
// Normally high - brought low for sync
#define SIG_SYNC_PIN PB1

// SPI SS - must be configured as output for SPI to work correctly
#define SPI_SS PB2

// Pixels on PB3 = MOSI, D11
// Normal low - brought high for white (with sync off)
#define SIG_PIXEL_PIN PB3

// AUX Signal, for when SPI idle
#define AUX_SIG_PIXEL_PIN PB0

#define SPI_MISO PB4
#define SPI_SCK PB5

//
// Gross manipulation of sync signal - supplements PWM
//
// SYNC_ON = sync pin LOW, SYNC_OFF = sync pin high
#define SYNC_ON (PORTB &= (~_BV(SIG_SYNC_PIN)))
#define SYNC_OFF (PORTB |= _BV(SIG_SYNC_PIN))
#define IS_SYNC_PIN_HIGH (PINB & _BV(SIG_SYNC_PIN))

// PIXEL_ON = pixel pin HIGH, PIXEL_OFF = pixel pin low
#define PIXEL_ON (PORTB |= _BV(SIG_PIXEL_PIN))
#define PIXEL_OFF (PORTB &= ~_BV(SIG_PIXEL_PIN))

// DDRB values with signal enabled or disabled
#define DDRB_SIGNAL_DISABLE \
    (_BV(SPI_SCK) | _BV(SPI_MISO) | \
     _BV(SPI_SS) | _BV(SIG_SYNC_PIN))

#define DDRB_SIGNAL_ENABLE (DDRB_SIGNAL_DISABLE | _BV(SIG_PIXEL_PIN))

//
// Timings
//
#define CYCLES_PER_US (F_CPU / 1000000)
#define CYCLES_PER_SCANLINE (64 * CYCLES_PER_US)
#define CYCLES_PER_HALF_SCANLINE (32 * CYCLES_PER_US)
#define CYCLES_HSYNC (4.7 * CYCLES_PER_US)
#define CYCLES_SHORTSYNC (2.35 * CYCLES_PER_US)
#define CYCLES_BROADSYNC ((32 - 4.7) * CYCLES_PER_US)
#define CYCLES_BACK_PORCH (5.7 * CYCLES_PER_US)
#define CYCLES_FRONT_PORCH (1.65 * CYCLES_PER_US)
#define CYCLES_TEXT_SAFE (41.5 * CYCLES_PER_US)
#define CYCLES_TEXT_START 240

//
// Global variables
//
#define DISPLAY_RAM_LEN 40
extern uint8_t display_buffer[];
#define display_ram (display_buffer + 1)
#define display_end (display_ram + DISPLAY_RAM_LEN)


#define LAST_TEXT_SAFE_LINE 229

// Pointers to the functions for execution at frame and line boundaries
// Frame function is called once per frame, and has about 80k cycles
// to execute
typedef void (*frame_function)(void);
extern frame_function frame_logic;

// Line function is called once per line and has about 150 cycles to execute
typedef void (*line_function)(uint8_t sync_count);
extern line_function line_logic;

// Initialization function
void init(void);

// Main, 50Hz display loop
void display_loop(void);

#endif /* DISPLAY_H_ */
